/**
 * @author emylyano3
 */

package org.generic;

import java.util.Vector;

import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
import javax.microedition.midlet.MIDletStateChangeException;

import org.generic.component.IdManager;
import org.generic.component.Resource;
import org.generic.component.ResourceProperty;
import org.generic.download.*;
import org.generic.extras.Debug;
import org.generic.rms.Rms;

public class AppCanvas extends Canvas implements Runnable, ScreenConstants, ResConstants, KeysConfig, DownloadListener {

	//**************************************************************************************************
	//	Constructor.
	//**************************************************************************************************
	
	private AppCanvas(TestMidlet midlet) {
		AppCanvas.midlet = midlet;
		new Thread (this).start();
		manager = new DownloadManager();
		serverUrl = midlet.getAppProperty("Server-URL");
		resources = new Vector();
	}
	
	public static AppCanvas getAppCanvas (TestMidlet midlet) {
		if (appCanvas == null) {
			appCanvas = new AppCanvas(midlet);
		}
		return appCanvas;
	}
	
	//**************************************************************************************************
	//	Public Methods.
	//**************************************************************************************************
	
	public void show() {
		display = Display.getDisplay(midlet);
		display.setCurrent(this);
		setFullScreenMode(true);
		SCREEN_WIDTH = getWidth();
		SCREEN_HEIGHT = getHeight();
	}
	
	protected void keyPressed(int keyCode) {
		Debug.out("Key pressed value : " + keyCode);
		userAction = true;
		switch (keyCode) {
			case KEY_SK_RIGHT:
				threadAlive = false;
				break;
			case KEY_LEFT:
			case KEY_RIGHT:
			case KEY_DOWN:
			case KEY_UP:
			default:
				break;
		}
		needToRepaint = true;
	}
	
	protected void keyReleased(int keyCode) {
		Debug.out("Key released value : " + keyCode);
		userAction = false;
	}
	
	protected void keyRepeated(int keyCode) {
		Debug.out("Key repeated value : " + keyCode);
		keyPressed(keyCode);
	}
	
	protected void pointerPressed(int x, int y) {
		Debug.out("Pointer pressed on: " + x + " " + y);
	}
	
	protected void pointerReleased(int x, int y) {
		Debug.out("Pointer released on: " + x + " " + y);
	}
	
	protected void pointerDragged(int x, int y) {
		Debug.out("Pointer dragged on: " + x + " " + y);
	}
	
	//**************************************************************************************************
	//	Private Methods.
	//**************************************************************************************************
	
	private String buildUrl(int id) {
		String resType = IdManager.getComponentType(id);
		String resExtension = IdManager.getComponentExtension(id);
		String url = serverUrl + SLASH + resType + SLASH + id + resExtension;
		return url;
	}
	
	private void updateState() {
		if (needToRepaint) {
			repaint();
			serviceRepaints();
		}
	}
	
	private void drawBackground(Graphics g) {
		g.setColor(A_BLUE);
		g.fillRect(X_OFFSET, Y_OFFSET, SCREEN_WIDTH, SCREEN_HEIGHT);
	}
	
	private void drawMessages(Graphics g) {
		g.setColor(WHITE);
		g.drawString("Downloading resources", SCREEN_WIDTH >> 1, SCREEN_HEIGHT >> 1, Graphics.HCENTER | Graphics.TOP);
	}

	private void drawSoftKeys (Graphics g) {
		g.setColor(WHITE);
		g.drawString("EXIT", SCREEN_WIDTH, SCREEN_HEIGHT, Graphics.RIGHT | Graphics.BASELINE);
	}
	
	private void drawImages (Graphics g) {
		Resource res;
		ResourceProperty prop;
		Image img;
		for (int i = 0; i < resources.size() ; i++) {
			res = (Resource) resources.elementAt(i);
			if (IdManager.getPrefixById(res.getResId()) == IdManager.IMAGE_PREFIX) {
				img = Image.createImage(res.getData(), 0x00, res.getData().length);
				prop = getProperties(res.getResId());
				g.drawImage(img, prop.getX(), prop.getY(), Graphics.LEFT | Graphics.TOP);
			}
		}
		drawImageText(g);
	}
	
	private void drawImageText (Graphics g) {
//		WebImage img;
//		byte xOff = 60;
//		for (int i = 0; i <= downloadedImageId ; i++) {
//			img = webImages[i];
//			g.drawString(img.getName(), img.getX() + xOff, img.getY(), Graphics.LEFT | Graphics.TOP);
//		}
	}
	
	protected void paint(Graphics g) {
		drawBackground(g);
		drawSoftKeys(g);
		drawImages(g);
		drawMessages(g);
		needToRepaint = false;
	}

	public void run() {
		currentPage = INITIAL_PAGE;
		loadPageResources(currentPage);
		while (threadAlive) {
			updateState();
		}
		try {
			midlet.destroyApp(true);
		} catch (MIDletStateChangeException e) {
			e.printStackTrace();
		}
	}

	/**
	 * To determine if the resource limit has been reached.
	 * */
	private boolean imageLimitReached() {
		return false;//downloadingImageId >= MAX_IMAGES - 1;
	}
	
	/**
	 * Persist the resource downloaded in the record store.
	 * @param id The id of the resource.
	 * @param name The name of the record store asociated to the resource type.
	 * @param data The data to be persisted.
	 * */
	private void persistData(String name, byte[] data) {
		System.out.println("Guardando la info");
		Rms.save(name, data);
	}
	
	/**
	 * Returns the properties associated to a resource.
	 * @param id The id of the resource to find properties.
	 * */
	private ResourceProperty getProperties (int id) {
		for (int i = 0; i < resourcesPropeties.length; i++) {
			if (resourcesPropeties[i].getId() == id) {
				return resourcesPropeties[i];
			}
		}
		return null;
	}
	
	private void loadPageResources(byte page) {
		for (int i = 0; i < resourcesToGet.size(); i++) {
			int id = ((Resource) resourcesToGet.elementAt(i)).getResId();
			String name = Integer.toString(id);
			byte[] data = null;
			if ((data = Rms.load(name)) != null) {
				resources.addElement(new Resource(id, page, data));
			} else if (!imageLimitReached()) {
				manager.addListener(this);
				manager.download(new DownloadRequest(buildUrl(id), id));
			}
		}
	}
	//**************************************************************************************************
	//	Listeners.
	//**************************************************************************************************
	
	public void downloadError(Exception e) {
		e.printStackTrace();
	}

	public void downloadCompleted(byte[] data, int id) {
		resources.addElement(new Resource(id, currentPage, data));
		needToRepaint = true;
		persistData(Integer.toString(id), data);
	}

	public void downloadStatus(int percent, int id) {
		System.out.println("Download Percent: " + percent + " of image: " + id);
	}
	
	//**************************************************************************************************
	//	Attributes.
	//**************************************************************************************************
	
	/**
	 * Objeto que gestionara las conexiones para realizar las bajadas de los recursos.
	 * */
	private static DownloadManager manager	= null;
	
	/** 
	 * Esto se va a cargar del XML que tengo en el jar.
	 * Contendra todos las propiedades de los recursos de la aplicacion (Ej.: x, y, w, h, color, etc.)
	 */
	private static ResourceProperty [] resourcesPropeties	= {
		new ResourceProperty(458754, "Pato", (short) 30,(short) 80),
		new ResourceProperty(458755, "Pocho", (short) 30, (short) 140),
		new ResourceProperty(458756, "Seba", (short) 30, (short) 200)
	};
	
	/**
	 * Contiene solo los id de los recursos del XML que necesitan ser descargados del servidor
	 * o levantados del RMS.
	 */
	private static Vector resourcesToGet 	= new Vector() {
		{ 
			addElement(new Resource(458754, (byte) 0));
			addElement(new Resource(458755, (byte) 0));
			addElement(new Resource(458756, (byte) 0));
		}
	};

	/**
	 * Contiene los recursos necesarios para la pantalla actual.
	 * Se cargan y descargan cada vez que se cambia de pantalla.
	 * */
	private static Vector resources			= null;

	/**
	 * Indica cual es el id de la pagina que se esta mostrando actualmente al usuario.
	 * */
	private static byte currentPage 		= -1;
	
	/**
	 * Puntero a la instancia del Canvas.
	 * */
	private static AppCanvas appCanvas 		= null;
	
	/**
	 * Refencia al midlet al que esta asociado este canvas.
	 * */
	private static TestMidlet midlet 		= null;
	
	/**
	 * Objeto para otorgar el display al canvas.
	 * */
	private static Display display 			= null;
	
	/**
	 * Se guarda la URL del servidor que se levanta del JAD.
	 * */
	private static String serverUrl			= null;
	
	/**
	 * Indica si el thread creado para el canvas esta corriendo o no.
	 * */
	public static boolean threadAlive 		= true;
	
	/**
	 * Sera true cuando haya modificaciones que requieran actualizacion de pintado.
	 * */
	public static boolean needToRepaint 	= false;
	
	/**
	 * Indica si hubo alguna accion del usuario.
	 * */
	public static boolean userAction 		= false;
	
	/**
	 * Caracter usado como separador de los directorios del repositorio.
	 * */
	public final static String SLASH = "/";
	
	//**************************************************************************************************
	//	Constants.
	//**************************************************************************************************
	/**
	 * Constante que se usara para indicar que se trata de la primer pagina de la aplicacion.
	 * */
	private final static byte INITIAL_PAGE 		= 0; 
	
	
	public static int SCREEN_WIDTH 	= 0;
	public static int SCREEN_HEIGHT = 0;

	public final static byte MAX_IMAGES 	= 5;
	public final static byte MAX_THREADS 	= 2;
	
	//**************************************************************************************************
	//	Inner Classes.
	//**************************************************************************************************
	
}
